# coding: iso-8859-15
# Author: Marc-Andre Belanger (centvingt@videotron.ca)
# Date: 14/09/2012
#
# This module includes the bob related code. 
# The emitter, receiver, sequencegenerator for travel, a generator and the actual bob node
from panda3d.core import *
from direct.interval.IntervalGlobal import *
import random

	
class BobEmitter:
	__gibson = ''
	__x = 0
	__y = 0
	__linkX = 0
	__linkY = 0
	__fork = ''
	def __init__(self, gibsonNode, x, y):
		self.__gibson = gibsonNode
		self.__x = x
		self.__y = y
		if x > 0:
			self.__linkX = 3
		elif x < 0:
			self.__linkX =  -3

		if y > 0:
			self.__linkY = 3
		elif y < 0:
			self.__linkY = -3

	def getPos(self):
		return Point3(self.__gibson.getX() + self.__x, self.__gibson.getY() + self.__y, 0)
		
	def getLinkPos(self):
		return Point3(self.__gibson.getX() + self.__linkX, self.__gibson.getY() + self.__linkY, 0)
		
class BobReceiver:
	__gibson = ''
	__x = 0
	__y = 0
	__linkX = 0
	__linkY = 0
	__bankX = 0
	__bankY = 0
	__fork = ''
	def __init__(self, gibsonNode, x, y, fork):
		self.__gibson = gibsonNode
		self.__x = x
		self.__y = y
		self.__fork = fork
		if y > 1:
			#northen receivers
			self.__linkY = 2
			self.__bankY = 2
			self.__bankX = x
			if x > 0:
				self.__linkX = 3
			elif x < 0:
				self.__linkX = -3
		elif y < -1:
			#southern receivers
			self.__linkY = -2
			self.__bankX = x
			self.__bankY = -2
			if x > 0:
				self.__linkX = 3
			elif x < 0:
				self.__linkX = -3
		else:
			self.__bankY = y
			if x > 1:
				# eastern receivers
				self.__linkX = 2
				self.__bankX = 2
			elif x < 1:
				# western receivers
				self.__linkX = -2
				self.__bankX = -2
			if y > 0:
				self.__linkY = 3
			elif y < 0:
				self.__linkY = -3
			
	def getBankPos(self):
		return Point3(self.__gibson.getX() + self.__bankX, self.__gibson.getY() + self.__bankY, 0)
			
	def getPos(self):
		return Point3(self.__gibson.getX() + self.__x, self.__gibson.getY() + self.__y, 0)
		
	def getLinkPos(self):
		return Point3(self.__gibson.getX() + self.__linkX, self.__gibson.getY() + self.__linkY, 0)
		
class BobSequenceGenerator:
	speedFactor = 1
	def __init__(self, speedFactor):
		self.speedFactor = speedFactor
	
	def getSequence(self, abob, emitter, receiver):
		# When getSequence is call, abob is already at bob_em location
		r1Interval = LerpPosInterval(abob, duration=0.9 * self.speedFactor, pos=receiver.getPos())
		r2Interval = LerpPosInterval(abob, duration=2.5 * self.speedFactor, pos=receiver.getBankPos())
		r3Interval = LerpPosInterval(abob, duration=1, pos=receiver.getLinkPos())

		e1Interval = LerpPosInterval(abob, duration=1.9 * self.speedFactor, pos=emitter.getLinkPos())
		

		if receiver.getLinkPos().getX() == emitter.getLinkPos().getX() or receiver.getLinkPos().getY() == emitter.getLinkPos().getY():
			return Sequence(e1Interval, r3Interval, r2Interval, r1Interval)
		else:
			#e2Interval = LerpPosInterval(abob, duration=1, pos=Point3(receiver.getLinkPos().getX(), emitter.getLinkPos().getY(), 0))
			if emitter.getPos().getX() == emitter.getLinkPos().getX():
			# emitter is N-S
				if receiver.getPos().getX() == receiver.getBankPos().getX():
					# if receiver on a EAST-WEST entry go x
					# move on x
					e2Interval = LerpPosInterval(abob, duration=1, pos=Point3(receiver.getLinkPos().getX(), emitter.getLinkPos().getY(), 0))
					return Sequence(e1Interval, e2Interval, r3Interval, r2Interval, r1Interval)
				else:
					#means receiver on a north-south entry
					if emitter.getLinkPos().getX() - receiver.getLinkPos().getX() > 0:
						offset = -3
					else:
						offset = 3
					# do a x move	
					e2Interval = LerpPosInterval(abob, duration=1, pos=Point3(emitter.getLinkPos().getX() + offset, emitter.getLinkPos().getY(), 0))
					# do a y move
					e3Interval = LerpPosInterval(abob, duration=1, pos=Point3(emitter.getLinkPos().getX() + offset, receiver.getLinkPos().getY(), 0))
					return Sequence(e1Interval, e2Interval, e3Interval, r3Interval, r2Interval, r1Interval)
			else:
			#emitter is E-W
				if receiver.getPos().getX() == receiver.getBankPos().getX():
					# if receiver on a EAST-WEST entry 
					if emitter.getLinkPos().getY() - receiver.getLinkPos().getY() > 0:
						offset = -3
					else:
						offset = 3
					# do a y move
					e2Interval = LerpPosInterval(abob, duration=1, pos=Point3(emitter.getLinkPos().getX(), emitter.getLinkPos().getY() + offset, 0))
					# do a x move
					e3Interval = LerpPosInterval(abob, duration=1, pos=Point3(receiver.getLinkPos().getX(), emitter.getLinkPos().getY() + offset, 0))
					return Sequence(e1Interval, e2Interval, e3Interval, r3Interval, r2Interval, r1Interval)
				else:
					#means receiver on a north-south entry
					# do a y move
					e2Interval = LerpPosInterval(abob, duration=1, pos=Point3(emitter.getLinkPos().getX(), receiver.getLinkPos().getY(), 0))
					return Sequence(e1Interval, e2Interval, r3Interval, r2Interval, r1Interval)
			
class BobGenerator:
	bobArray = []
	def __init__(self, count, speedfactor, np, gibsonarray):
		self.__count = count
		self.__sf = speedfactor
		self.__np = np
		self.gibsonarray = gibsonarray
		
		for i in range(15):
			bob_em = random.choice(self.gibsonarray).getRandomEmitter()
			self.bobArray.append( Bob('aBob', speedfactor, gibsonarray, self) )
			self.bobArray[i].reparentTo(np)
			
		
class Bob(NodePath):
	
	def __init__(self, aName, speed, gibsonarray, gen):
		NodePath.__init__(self, aName)
		NodePath.setPythonTag(self, "subclass", self)
		
		self.gen = gen
		self.ga = gibsonarray
		self.generator = BobSequenceGenerator(speed)
		self.seeker = loader.loadModel(Filename("models/sphere"))
		self.seeker.setScale(0.025)
		self.seeker.setPos(0,0,0.025)
		
		self.seeker.reparentTo(self)
		self.setSequence()

	def setSequence(self):
		seeker_em = random.choice(self.ga).getRandomEmitter()
		self.setPos(seeker_em.getPos())
		sequence = self.generator.getSequence(self, seeker_em, random.choice(self.ga).getRandomReceiver())
		sequence.append(Func(self.setSequence))
		#print sequence
		sequence.start()


